﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

namespace Pisces
{
    /**
     * 对象池(非线程安全)
     */
    public class ObjectPool<T> where T : class, InterfacePoolObject, new()
    {
        /**
         * 对象链表
         */
        private Stack<T> stack;

        /**
         * 最大容量,默认4个
         */
        private int maxCapacity;

        public ObjectPool()
        {
            this.maxCapacity = 8;
            stack = new Stack<T>();
        }

        public ObjectPool(int capacity)
        {
            init(capacity);
        }

        private void init(int capacity)
        {
            this.maxCapacity = capacity;
            if (capacity == 0)
            {
                stack = new Stack<T>();
            }
            else
            {
                stack = new Stack<T>(capacity);
            }
        }
        
        /**
         * 分配一个对象
         */
        public T allocate()
        {
            T obj = null;
            if (stack.Count >= maxCapacity)
            {
                obj = new T();
            }
            else
            {
                obj = stack.Pop();
            }

            try
            {
                obj.allocate();
            }
            catch (Exception e)
            {
                PiscesLog.error(string.Format("对象池分配对象异常，message:{0}, stacktrace:{1}", e.Message, e.StackTrace));
            }

            return obj;
        }

        /**
         * 回收一个对象
         */
        public void release(T poolObject)
        {
            if (poolObject == null)
            {
                return;
            }

            if (stack.Count >= maxCapacity)
            {
                poolObject.release();
                return;
            }
            
            poolObject.release();
            
            stack.Push(poolObject);
        }

        public void clear()
        {
            int count = stack.Count;
            for (int i = 0; i < count; i++)
            {
                T poolObject = stack.Pop();
                if (poolObject == null)
                {
                    continue;
                }
                
                poolObject.release();
            }
        }
        
    }
}